const jwt = require('jsonwebtoken');
const { User } = require('../models');

const authenticateToken = async (req, res, next) => {
  try {
    const authHeader = req.headers['authorization'];
    const token = authHeader && authHeader.split(' ')[1];

    if (!token) {
      return res.status(401).json({
        error: '访问令牌缺失'
      });
    }

    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    
    // 验证用户是否存在且活跃
    const user = await User.findByPk(decoded.userId);
    if (!user || !user.is_active) {
      return res.status(401).json({
        error: '用户不存在或已被禁用'
      });
    }

    // 扩展req.user对象，包含更多用户信息
    req.user = {
      id: user.id,
      username: user.username,
      email: user.email,
      role: user.role,
      permissions: user.permissions || {}
    };
    
    next();
  } catch (error) {
    if (error.name === 'JsonWebTokenError') {
      return res.status(401).json({
        error: '无效的访问令牌'
      });
    }
    
    if (error.name === 'TokenExpiredError') {
      return res.status(401).json({
        error: '访问令牌已过期'
      });
    }
    
    console.error('认证中间件错误:', error);
    res.status(500).json({
      error: '认证过程中发生错误'
    });
  }
};

const optionalAuth = async (req, res, next) => {
  try {
    const authHeader = req.headers['authorization'];
    const token = authHeader && authHeader.split(' ')[1];

    if (token) {
      const decoded = jwt.verify(token, process.env.JWT_SECRET);
      const user = await User.findByPk(decoded.userId);
      
      if (user && user.is_active) {
        req.user = {
          id: user.id,
          username: user.username,
          email: user.email,
          role: user.role,
          permissions: user.permissions || {}
        };
      }
    }
    
    next();
  } catch (error) {
    // 可选认证失败时不阻止请求继续
    next();
  }
};

/**
 * 检查用户是否为管理员
 */
const isAdmin = async (req, res, next) => {
  try {
    if (!req.user) {
      return res.status(401).json({
        error: '需要登录才能访问'
      });
    }
    
    const user = await User.findByPk(req.user.id);
    if (!user || !user.isAdmin()) {
      return res.status(403).json({
        error: '需要管理员权限'
      });
    }
    
    next();
  } catch (error) {
    console.error('权限检查错误:', error);
    res.status(500).json({
      error: '权限检查过程中发生错误'
    });
  }
};

/**
 * 检查用户是否为超级管理员
 */
const isSuperAdmin = async (req, res, next) => {
  try {
    if (!req.user) {
      return res.status(401).json({
        error: '需要登录才能访问'
      });
    }
    
    const user = await User.findByPk(req.user.id);
    if (!user || user.role !== 'superadmin') {
      return res.status(403).json({
        error: '需要超级管理员权限'
      });
    }
    
    next();
  } catch (error) {
    console.error('权限检查错误:', error);
    res.status(500).json({
      error: '权限检查过程中发生错误'
    });
  }
};

/**
 * 检查用户是否为版主或管理员
 */
const isModerator = async (req, res, next) => {
  try {
    if (!req.user) {
      return res.status(401).json({
        error: '需要登录才能访问'
      });
    }
    
    const user = await User.findByPk(req.user.id);
    if (!user || !user.isModerator()) {
      return res.status(403).json({
        error: '需要版主或管理员权限'
      });
    }
    
    next();
  } catch (error) {
    console.error('权限检查错误:', error);
    res.status(500).json({
      error: '权限检查过程中发生错误'
    });
  }
};

/**
 * 检查用户是否具有指定角色
 * @param {string|string[]} roles - 需要检查的角色或角色数组
 * @returns {function} Express中间件
 */
const hasRole = (roles) => {
  return async (req, res, next) => {
    try {
      if (!req.user) {
        return res.status(401).json({
          error: '需要登录才能访问'
        });
      }
      
      const user = await User.findByPk(req.user.id);
      if (!user || !user.hasRole(roles)) {
        return res.status(403).json({
          error: '权限不足，需要更高级别的角色'
        });
      }
      
      next();
    } catch (error) {
      console.error('角色检查错误:', error);
      res.status(500).json({
        error: '角色检查过程中发生错误'
      });
    }
  };
};

/**
 * 检查用户是否具有指定权限
 * @param {string|string[]} permissions - 需要检查的权限或权限数组
 * @returns {function} Express中间件
 */
const hasPermission = (permissions) => {
  return async (req, res, next) => {
    try {
      if (!req.user) {
        return res.status(401).json({
          error: '需要登录才能访问'
        });
      }
      
      const user = await User.findByPk(req.user.id);
      
      if (!user) {
        return res.status(403).json({
          error: '用户不存在'
        });
      }
      
      // 将单个权限转换为数组
      const permissionList = Array.isArray(permissions) ? permissions : [permissions];
      
      // 检查用户是否拥有所有指定的权限
      const hasAllPermissions = permissionList.every(permission => 
        user.hasPermission(permission)
      );
      
      if (!hasAllPermissions) {
        return res.status(403).json({
          error: '权限不足，需要更高级别的权限'
        });
      }
      
      next();
    } catch (error) {
      console.error('权限检查错误:', error);
      res.status(500).json({
        error: '权限检查过程中发生错误'
      });
    }
  };
};

/**
 * 检查用户是否拥有资源所有权
 * @param {function} getResourceUserId - 从请求中获取资源所有者ID的函数
 * @returns {function} Express中间件
 */
const isResourceOwner = (getResourceUserId) => {
  return async (req, res, next) => {
    try {
      if (!req.user) {
        return res.status(401).json({
          error: '需要登录才能访问'
        });
      }
      
      const resourceUserId = await getResourceUserId(req);
      
      // 如果是管理员，允许访问任何资源
      const user = await User.findByPk(req.user.id);
      if (user && user.isAdmin()) {
        return next();
      }
      
      // 检查当前用户是否是资源所有者
      if (req.user.id !== resourceUserId) {
        return res.status(403).json({
          error: '权限不足，只有资源所有者才能执行此操作'
        });
      }
      
      next();
    } catch (error) {
      console.error('所有权检查错误:', error);
      res.status(500).json({
        error: '所有权检查过程中发生错误'
      });
    }
  };
};

/**
 * 记录API访问日志
 */
const logApiAccess = (req, res, next) => {
  const start = Date.now();
  
  // 捕获响应完成事件
  res.on('finish', () => {
    const duration = Date.now() - start;
    const userId = req.user ? req.user.id : 'anonymous';
    const userRole = req.user ? req.user.role : 'none';
    
    console.log(`[${new Date().toISOString()}] ${req.method} ${req.originalUrl} - ${res.statusCode} - ${duration}ms - User: ${userId} - Role: ${userRole}`);
    
    // 这里可以将日志存储到数据库或发送到监控系统
  });
  
  next();
};

module.exports = {
  authenticateToken,
  optionalAuth,
  isAdmin,
  isSuperAdmin,
  isModerator,
  hasRole,
  hasPermission,
  isResourceOwner,
  logApiAccess
}; 